package com.ccn.qrcode.utils;

import com.ccn.qrcode.common.Constant;
import com.ccn.qrcode.common.FileChoiseEnum;
import com.ccn.qrcode.pojo.QrcodeCell;
import com.ccn.qrcode.pojo.QrcodeFilePojo;
import com.ccn.qrcode.service.QrcodeFileService;
import com.ccn.qrcode.utils.qrcodefile.QrcodeFileUtils;
import com.google.common.collect.Lists;
import com.google.zxing.common.BitMatrix;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.*;
import java.util.List;

import static com.ccn.qrcode.utils.MatrixToImageWriter.getMiddleSize;

/**
 * 自定义绘制矩阵
 *
 * @author tig
 */
public class SelfMatrixToImageWriter {
    private static final Logger logger = LoggerFactory.getLogger(SelfMatrixToImageWriter.class);

    /**
     * 文件图形
     */
    private static final int BLACK = 0xFF000000;
    private static final int WHITE = 0xFFFFFFFF;


    private SelfMatrixToImageWriter() {
    }

    public static BufferedImage toBufferedImage(BitMatrix matrix, QrcodeFilePojo filePojo) throws IOException {
        int width = matrix.getWidth();
        int height = matrix.getHeight();
        //获取绘图区，最后一个点位置
        int beginWidth = 0;
        int beginHeight = 0;
        int endWidth = 0;
        int endHeight = 0;
        // 中间点，用来确定各个区绘制图片颜色
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB_PRE);
        // 1.先知道文件绘图区的大小
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                //二维码有数据，开始做图形折叠
                if (matrix.get(x, y)) {
                    // 找出第一个点
                    if (beginWidth == 0) {
                        beginWidth = x;
                        beginHeight = y;
                    }
                    // 找到最后一个点
                    if (endWidth < x) {
                        endWidth = x;
                    }
                    if (endHeight < y) {
                        endHeight = y;
                    }
                }
            }
        }
        //获取图片颜色集
        int middle = getMiddleSize(beginWidth, endWidth);
        //计算resize
        int lastRowSize = MatrixToImageWriter.getRowSize(beginWidth, beginHeight, endWidth, endHeight);
        //8;6;2;8
        String[] fileColors = filePojo.getFileColor().split(";");
        if (fileColors.length != 4) {
            logger.error("文件文本：" + filePojo.getFileName() + "解析出错");
        }
        //分区绘制二维码
        /**
         *  第二象限  - 第一象限
         * --------------------
         *  第三象限  - 第四象限
         */
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                //绘制第一象限
                if (x >= middle && y <= middle) {
                    image.setRGB(x, y, matrix.get(x, y) ? QrcodeFileUtils.fileColor(fileColors[0]) : WHITE);
                }
                //绘制第二象限
                if (x < middle && y < middle) {
                    image.setRGB(x, y, matrix.get(x, y) ? QrcodeFileUtils.fileColor(fileColors[1]) : WHITE);
                }
                //绘制第三象限
                if (x <= middle && y >= middle) {
                    image.setRGB(x, y, matrix.get(x, y) ? QrcodeFileUtils.fileColor(fileColors[3]) : WHITE);
                }
                //绘制第四象限
                if (x > middle && y > middle) {
                    image.setRGB(x, y, matrix.get(x, y) ? QrcodeFileUtils.fileColor(fileColors[2]) : WHITE);
                }
            }
        }
        //绘出来黑点
        Random r = new Random();
        int data = r.nextInt(10);
        List<Map<Integer, Integer>> scopeList = Lists.newArrayList();
        //1.先确定两种类型的点。是6个还是8个
        int step = Constant.MIN;
        if (data > 5) {
            step = Constant.MAX;
        }
        //确定绘制的点数
        for (int i = 0; i < Constant.SCOPE; i++) {
            Random tmp = new Random();
            int x = tmp.nextInt(endWidth - beginWidth + 1) + beginWidth;
            int y = tmp.nextInt(endHeight - beginHeight + 1) + beginHeight;
            getScopList(scopeList, x, y, Constant.MAX, beginWidth, beginHeight,0);
        }

        for (int i = 0; i < scopeList.size(); i++) {
            Map<Integer, Integer> map = scopeList.get(i);
            Iterator<Map.Entry<Integer, Integer>> entries = map.entrySet().iterator();
            while (entries.hasNext()) {
                Map.Entry<Integer, Integer> entry = entries.next();
                image.setRGB(entry.getKey(), entry.getValue(), BLACK);
            }
        }
        return image;
    }

    public static List<Map<Integer, Integer>> getScopList(List<Map<Integer, Integer>> scopeList, int x, int y, int stepType, int min, int max, int num) {
        // 判断是不是6
        if (stepType == Constant.MIN) {
            /**
             * 第一组六个点
             *  *** x
             *  ***
             *  y
             */
            // 可以用一组map
            Map<Integer, Integer> put1 = new HashMap<>();
            put1.put(x, y);
            Map<Integer, Integer> put2 = new HashMap<>();
            put2.put(x + 1, y);
            Map<Integer, Integer> put3 = new HashMap<>();
            put3.put(x + 2, y);
            Map<Integer, Integer> put4 = new HashMap<>();
            put4.put(x, y + 1);
            Map<Integer, Integer> put5 = new HashMap<>();
            put5.put(x + 1, y + 1);
            Map<Integer, Integer> put6 = new HashMap<>();
            put6.put(x + 2, y + 1);
            if (scopeList.contains(put1) || scopeList.contains(put3)
                    || scopeList.contains(put5) || scopeList.contains(put6)) {
                //加上防止死循环标志
                if(num < 10){
                    //重新随机生成初始点
                    Random r = new Random();
                    int randWidth = r.nextInt(max - min + 1) + min;
                    int randHeight = r.nextInt(max - min + 1) + min;
                    getScopList(scopeList, randWidth, randHeight, stepType, min, max, num+1);
                }
            } else {
                scopeList.add(put1);
                scopeList.add(put2);
                scopeList.add(put3);
                scopeList.add(put4);
                scopeList.add(put5);
                scopeList.add(put6);
            }
        }

        //不绘制6 肯定绘制9
        if (stepType == Constant.MAX) {
            /**
             * 第二组九个点
             *  *   *   * x
             *  *   *   *
             *  *   *   *
             *  y
             */
            Map<Integer, Integer> put1 = new HashMap<>();
            put1.put(x, y);
            Map<Integer, Integer> put2 = new HashMap<>();
            put2.put(x + 1, y);
            Map<Integer, Integer> put3 = new HashMap<>();
            put3.put(x + 2, y);

            Map<Integer, Integer> put4 = new HashMap<>();
            put4.put(x, y + 1);
            Map<Integer, Integer> put5 = new HashMap<>();
            put5.put(x + 1, y + 1);

            Map<Integer, Integer> put6 = new HashMap<>();
            put6.put(x + 1, y + 2);

            Map<Integer, Integer> put7 = new HashMap<>();
            put7.put(x, y + 2);

            Map<Integer, Integer> put8 = new HashMap<>();
            put8.put(x + 2, y + 1);
            Map<Integer, Integer> put9 = new HashMap<>();
            put9.put(x + 2, y + 2);
            if (scopeList.contains(put1) || scopeList.contains(put3) || scopeList.contains(put7) || scopeList.contains(put9)) {
                if(num <10){
                    // 重新随机点
                    //重新随机生成初始点
                    Random r = new Random();
                    int randWidth = r.nextInt(max - min + 1) + min;
                    int randHeight = r.nextInt(max - min + 1) + min;
                    getScopList(scopeList, randWidth, randHeight, stepType, min, max, num+1);
                }
            } else {
                scopeList.add(put1);
                scopeList.add(put2);
                scopeList.add(put3);
                scopeList.add(put4);
                scopeList.add(put5);
                scopeList.add(put6);
                scopeList.add(put7);
                scopeList.add(put8);
                scopeList.add(put9);
            }
        }
        return scopeList;
    }


}
